home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
MacWorld 1996 March
/
MacWorld 03:96.toast
/
Graphics
/
clip2gif 0.7.2
/
Calling clip2gif from C
/
example-cgi.c
< prev
next >
Wrap
Text File
|
1995-12-14
|
10KB
|
335 lines
/*
* Demo of using clip2gif with the CFM PPC
*
* PLASE READ!
*
* This CGI program returns a GIF showing the trajectory of a planar parallel robot.
* If should be saved as robot.acgi. It can be called with the following URLs:
*
* http://your.hostname/robot.acgi?k=h&w=5&h=7&n=10
* -> html page wrapping an image of a robot with a motion of width 20 * w,
* height 10 * h, and 2 * n intermediate positions
* (each argument is coded in 1 char :-( )
*
* http://your.hostname/robot.acgi?k=g&w=20&h=30&n=10
* -> corresponding gif image
*
* To compile it, create a new PPC project with CW7 (other versions and compilers
* might also work, but haven't been tested), include example-cgi.c, LoadClip2Gif.c,
* InterfaceLib, MWCRuntime.Lib, MathLib and AppleScriptLib, and build it as "robot.acgi".
* It should have at least canBackground and isHightLevelEventAware bits set.
* Copy it anywhere in the HTTP server document tree. clip2gif should be on the same
* volume, or in the same folder if there are former versions on the same volume.
*
* To quit robot.acgi, send it a quit AppleEvent ('tell app "robot.acgi" to quit'
* in AppleScript), or type command-q.
*
*** Warning: The purpose of this CGI is *not* to show The Best Way to implement a CGI,
*** but how simple it is to use clip2gif.
*
* Copyright 1995, Yves Piguet. All rights reserved.
*
* Can be distributed only as part of the whole clip2gif package.
*
* If you use this source code, acknowledgment on your web pages would be appreciated.
*
* Thanks!
*/
#include <fp.h> // math functions
#include <AppleEvents.h>
#include "LoadClip2Gif.h"
int done;
static StringPtr http_html_header = "\pHTTP/1.0 200 OK\r\n\Content-type: text/html\r\n\r\n";
static StringPtr http_gif_header = "\pHTTP/1.0 200 OK\r\nContent-type: image/gif\r\n\r\n";
static StringPtr http_error = "\pHTTP/1.0 400 ERROR\r\n\r\n";
// HTML doc. Not that nice to have it here in pascal strings, but you'd been warned.
// The inline image URL can become robot.acgi?k=h&w=2&h=3&k=g or even
// robot.acgi?&k=g , but it still works.
static StringPtr html_t1 = "\p<html><header><title>Robot</title></header>\r\n<body><h1>Robot</h1>"
"Planar parallel robot with horizontal tool base.<p>"
"<img src=robot.acgi?";
static StringPtr html_t2 = "\p&k=g><p>\r\n"
"<hr><h2>New Move</h2>"
"<form action=robot.acgi method=get>\r\n"
"<input type=hidden name=k value=h>\r\n"
"Width: <select name=w>";
static StringPtr html_t3 = "\p<option value=1>20</option><option value=2>40</option>"
"<option value=3>60</option><option value=4>80</option>\r\n"
"<option value=5 selected>100</option><option value=6>120</option>"
"<option value=7>140</option><option value=8>160</option>"
"</select><p>\r\n";
static StringPtr html_t4 = "\pHeight: <select name=h>"
"<option value=0>0</option><option value=1>10</option>"
"<option value=2>20</option><option value=3>30</option>\r\n"
"<option value=4 selected>40</option><option value=5>50</option>"
"<option value=6>60</option><option value=7>70</option>";
static StringPtr html_t5 = "\p<option value=8>80</option>"
"</select><p>\r\n"
"Intermediate positions: <select name=n>\r\n"
"<option value=0>0</option><option value=1>2</option>"
"<option value=2>4</option><option value=4 selected>8</option>"
"<option value=6>12</option><option value=9>18</option>";
static StringPtr html_t6 = "\p</select><p>\r\n"
"<input type=submit value=Submit></form><p>\r\n"
"<hr><address>CGI written by "
"<a href=mailto:piguet@ia.epfl.ch>Yves Piguet</a></address>"
"</body></html>\r\n";
// some geometric constants
#define iw 240
#define ih 200
#define top 5
#define ground 195
#define center 120
#define shoulder 20
#define arm 105
#define forearm 110
#define paralw 10
static void InitToolbox()
{
InitGraf((Ptr)&qd.thePort);
InitFonts();
InitWindows();
InitMenus();
TEInit();
InitDialogs(0L);
InitCursor();
}
static pascal OSErr MyHandleQuit(AppleEvent *evt, AppleEvent *reply, long refCon)
{
#pragma unused(evt, reply, refCon)
done = 1;
return noErr;
}
static void DrawRobot(short a, short b)
// draws the robot arms to point (a, b) over the ground
{
double x, y, tmp, x1, y1;
short a1, b1;
a1 = a - shoulder;
b1 = ground - top - b;
tmp = a1 * a1 + b1 * b1;
x1 = (tmp + arm * arm - forearm * forearm) / (2 * tmp);
y1 = sqrt(arm * arm / tmp - x1 * x1);
x = a1 * x1 - b1 * y1;
y = b1 * x1 + a1 * y1;
MoveTo(center - shoulder, top);
Line((short)x, (short)y);
LineTo(center + a, ground - b);
Line(paralw, 0);
MoveTo(center - shoulder + (short)x, top + (short)y);
Line(paralw, 0);
MoveTo(center - shoulder + paralw, top);
Line((short)x, (short)y);
LineTo(center + a + paralw, ground - b);
a1 = a + shoulder;
tmp = a1 * a1 + b1 * b1;
x1 = (tmp + arm * arm - forearm * forearm) / (2 * tmp);
y1 = sqrt(arm * arm / tmp - x1 * x1);
x = a1 * x1 + b1 * y1;
y = b1 * x1 - a1 * y1;
MoveTo(center + shoulder + paralw, top);
Line((short)x, (short)y);
LineTo(center + a + paralw, ground - b);
}
static pascal OSErr MyHandleSDOC(AppleEvent *evt, AppleEvent *reply, long refCon)
{
#pragma unused(refCon)
Offscreen os;
short width = 100, height = 40, n = 10, i;
unsigned char kind = 'h';
DescType typeCode;
Size actualSize;
Str255 arg;
AEDesc replyStr;
Handle gifHandle;
OSErr err;
err = AEGetParamPtr(evt, 'kfor', typeChar, &typeCode, (Ptr)(arg + 1), 250, &actualSize);
if (err != noErr)
goto oops;
arg[0] = actualSize;
for (i = 0; i < arg[0] - 2; i++)
if (arg[i + 2] == '=')
switch (arg[i + 1])
{
case 'k':
case 'K':
kind = arg[i + 3] | 32; // lowercase
if (kind != 'g')
kind = 'h';
arg[i + 2] = 'g'; // ready for the inline image URL
break;
case 'w':
case 'W':
if (arg[i + 3] >= '0' && arg[i + 3] <= '9')
width = 20 * (arg[i + 3] - '0');
else
width = 100;
break;
case 'h':
case 'H':
if (arg[i + 3] >= '0' && arg[i + 3] <= '9')
height = 10 * (arg[i + 3] - '0');
else
height = 40;
break;
case 'n':
case 'N':
if (arg[i + 3] >= '0' && arg[i + 3] <= '9')
n = 2 * (arg[i + 3] - '0');
else
n = 8;
break;
}
if (kind == 'h') // HTML
{
replyStr.descriptorType = typeChar;
err = PtrToHand((Ptr)(http_html_header + 1), &replyStr.dataHandle, http_html_header[0]);
err = PtrAndHand((Ptr)(html_t1 + 1), replyStr.dataHandle, html_t1[0]);
err = PtrAndHand((Ptr)(arg + 1), replyStr.dataHandle, arg[0]); // part of gif URL
err = PtrAndHand((Ptr)(html_t2 + 1), replyStr.dataHandle, html_t2[0]);
err = PtrAndHand((Ptr)(html_t3 + 1), replyStr.dataHandle, html_t3[0]);
err = PtrAndHand((Ptr)(html_t4 + 1), replyStr.dataHandle, html_t4[0]);
err = PtrAndHand((Ptr)(html_t5 + 1), replyStr.dataHandle, html_t5[0]);
err = PtrAndHand((Ptr)(html_t6 + 1), replyStr.dataHandle, html_t6[0]);
}
else // GIF
{
err = BeginOffscreen(&os, iw, ih, 4, colorPaletteSystem);
if (err != noErr)
goto oops;
// now the QuickDraw port is ok; we can draw directly
PenSize(2, 2);
// arms in the intermediate positions
ForeColor(cyanColor);
for (i = 1; i <= n; i++)
DrawRobot(-width / 2 + width * i / (n + 1), height * i / (n + 1));
// arms in the extreme positions
ForeColor(blackColor);
DrawRobot(-width / 2, 0);
DrawRobot(width / 2, height);
// top (where the robot is fixed)
ForeColor(redColor);
PenSize(4, 4);
MoveTo(0, top);
Line(iw, 0);
PenSize(1, 1);
// that's it!
//#ifdef noooooh
{
// if you want to check the image before launching your http server,
// enable these lines and send robot.acgi the following AS command:
// «event WWWΩsdoc» given «class kfor»:"k=g&w=5&h=5&n=5"
FSSpec spec;
FSMakeFSSpec(0, 0, "\ptest.gif", &spec);
(void)ConvertPixmapToGIFFile(os.pixmap, &spec, 1, transparencyFirstPixel);
}
//#endif
err = ConvertPixmapToGIFHandle(os.pixmap, &gifHandle, 1, transparencyFirstPixel);
if (err == noErr) // concat. the http GIF header and the gif
{
replyStr.descriptorType = typeChar;
err = PtrToHand((Ptr)(http_gif_header + 1), &replyStr.dataHandle, http_gif_header[0]);
err = HandAndHand(gifHandle, replyStr.dataHandle);
DisposHandle(gifHandle);
}
(void)DisposeOffscreen(&os);
}
oops:
if (err != noErr)
{
replyStr.descriptorType = typeChar;
err = PtrToHand((Ptr)(http_error + 1), &replyStr.dataHandle, http_error[0]);
}
(void)AEPutParamDesc(reply, keyDirectObject, &replyStr);
DisposHandle(replyStr.dataHandle);
return noErr;
}
void main(void)
{
EventRecord myEvent;
OSErr err;
InitToolbox(); // standard stuff
// uses the CFM to gain access to clip2gif exported functions
err = LoadClip2Gif();
if (err != noErr)
{
SysBeep(1); // Cannot load clip2gif
return;
}
// installs AppleEvent handlers for quit and sdoc
(void)AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
NewAEEventHandlerProc(MyHandleQuit), 0L, 0);
(void)AEInstallEventHandler('WWWΩ', 'sdoc',
NewAEEventHandlerProc(MyHandleSDOC), 0L, 0);
// main event loop
for (done = 0; !done;)
{
WaitNextEvent(everyEvent, &myEvent, 30L, 0L);
switch (myEvent.what)
{
case keyDown:
if (myEvent.modifiers & cmdKey
&& (myEvent.message & charCodeMask) == 'q') // command-q -> quit
done = 1;
break;
case kHighLevelEvent:
(void)AEProcessAppleEvent(&myEvent);
break;
}
}
}